﻿using System;
using System.Reflection;
/// <summary>
/// 对象克隆
/// </summary>
namespace MDK.Common
{
    public class ObjectCloneHelper
    {
        /// <summary>
        /// 对象克隆
        /// </summary>
        /// <param name="destination">目标对象</param>
        /// <param name="source">原始对象</param>
        /// <param name="isShallowCopy">true:浅克隆/false:深克隆</param>
        public static int Copy(object destination, object source, bool isShallowCopy = false)
        {
            if (destination == null || source == null)
            {
                return 0;
            }

            return Copy(destination, source, source.GetType(), isShallowCopy);
        }
        /// <summary>
        /// 对象克隆
        /// </summary>
        /// <param name="destination">目标对象</param>
        /// <param name="source">原始对象</param>
        /// <param name="type">类型</param>
        /// <param name="isShallowCopy">true:浅克隆/false:深克隆</param>
        public static int Copy(object destination, object source, Type type, bool isShallowCopy = false)
        {
            if (destination == null || source == null)
            {
                return 0;
            }
            int i = 0;
            Type desType = destination.GetType();
            foreach (FieldInfo mi in type.GetFields())
            {
                try
                {
                    FieldInfo des = desType.GetField(mi.Name);
                    if (des != null && des.FieldType == mi.FieldType)
                    {
                        if (isShallowCopy && mi.FieldType.Namespace != "System") continue;

                        des.SetValue(destination, mi.GetValue(source));
                        i++;
                    }
                }
                catch
                {
                }
            }

            foreach (PropertyInfo pi in type.GetProperties())
            {
                PropertyInfo des = desType.GetProperty(pi.Name);
                if (des != null && des.PropertyType == pi.PropertyType && des.CanWrite && pi.CanRead)
                {
                    if (isShallowCopy && pi.PropertyType.Namespace != "System") continue;

                    des.SetValue(destination, pi.GetValue(source, null), null);
                    i++;
                }
            }
            return i;
        }

        /// <summary>
        /// 该方法适应有类型修饰（int?与int、Nullable<int>与int）类的属性之间的值得复制
        /// </summary>
        /// <param name="destination">目标对象</param>
        /// <param name="source">原始对象</param>
        /// <param name="isShallowCopy">true:浅克隆/false:深克隆</param>
        public static int Copy1(object destination, object source, bool isShallowCopy = false)
        {
            if (destination == null || source == null)
            {
                return 0;
            }

            return Copy1(destination, source, source.GetType(), isShallowCopy);
        }
        /// <summary>
        /// 对象克隆
        /// </summary>
        /// <param name="destination">目标对象</param>
        /// <param name="source">原始对象</param>
        /// <param name="type">类型</param>
        /// <param name="isShallowCopy">true:浅克隆/false:深克隆</param>
        public static int Copy1(object destination, object source, Type type, bool isShallowCopy = false)
        {
            if (destination == null || source == null)
            {
                return 0;
            }
            int i = 0;
            Type desType = destination.GetType();
            foreach (FieldInfo mi in type.GetFields())
            {
                try
                {
                    FieldInfo des = desType.GetField(mi.Name);
                    if (des != null && des.FieldType == mi.FieldType)
                    {
                        if (isShallowCopy && mi.FieldType.Namespace != "System") continue;

                        des.SetValue(destination, mi.GetValue(source));
                        i++;
                    }
                }
                catch
                {
                }
            }

            foreach (PropertyInfo pi in type.GetProperties())
            {
                try
                {
                    PropertyInfo des = desType.GetProperty(pi.Name);
                    //System.Nullable`1[]
                    if (des == null) continue;
                    //if(des.PropertyType)
                    var desPName = des.PropertyType.ToString();
                    var piPName = pi.PropertyType.ToString();

                    desPName = desPName.Replace("System.Nullable`1[", "");
                    desPName = desPName.Replace("]", "");
                    desPName = desPName.Replace("?", "");

                    piPName = piPName.Replace("System.Nullable`1[", "");
                    piPName = piPName.Replace("]", "");
                    piPName = piPName.Replace("?", "");

                    if (des != null && desPName == piPName && des.CanWrite && pi.CanRead)
                    {
                        if (isShallowCopy && pi.PropertyType.Namespace != "System") continue;

                        des.SetValue(destination, pi.GetValue(source, null), null);
                        i++;
                    }
                }
                catch
                {
                }
            }
            return i;
        }
    }
}
